<script setup lang="ts">
import { inject, nextTick, onMounted, reactive, ref, watch } from 'vue';

import axios from 'axios';
import {
  ElAlert,
  ElCol,
  ElCollapse,
  ElCollapseItem,
  ElInput,
  ElMessage,
  ElOption,
  ElRadio,
  ElRadioGroup,
  ElRow,
  ElSelect,
  ElTable,
  ElTableColumn,
} from 'element-plus';

import { vectorServiceApi } from '#/api';
import {
  GradualValueRender,
  HierarchicalRender,
} from '#/assets/visualization-template';
import { usePublicStore } from '#/store';

const publicStore = usePublicStore();
const currentLayer = inject('currentSelectedLayer') as any;
const activeNames = ref(['renderParams']);
// const gradualValueRender = new GradualValueRender()
// const basedRule = ref('global')
const fieldList = ref<Array<any>>(); // 当前图层的字段列表
const currentLegendList = ref<any>(); // 储存当前颜色数组和字段唯一值，以及两者的对应关系，方便后续渲染
const lineWidthRange = ref([1, 10]); // 线宽范围
const address = ref('');
const gradualValueRender = new GradualValueRender(); // 调用渐变值渲染方法
const hierarchicalRender = new HierarchicalRender(); // 调用分级的分级函数
const ODOptions = reactive({
  layer: currentLayer.value,
  isFieldBasedRender: false,
  field: '', // 线宽和颜色变化所依据的字段
  sort: 'asc',
  layout: {
    height: 5,
    'source-position': [118.9126, 32.1002],
    'is-great-circle': false,
  },
  paintBasedField: {
    'source-color': '#65e740',
    'target-color': [''],
    'line-width': [0],
  },
  paint: {
    'source-color': '#65e740',
    'target-color': '#f03124',
    'line-width': 2,
  },
  mapLayer: {} as any,
});
interface ColorRampItem {
  id: number;
  label: string;
  value: string;
  image: string;
}
const colorRamp = ref('gradual_ramp1');
const colorRampSelect = ref(); // 用于获取下拉框dom
const colorRampList = ref<Array<ColorRampItem>>([
  {
    id: 1,
    label: '色带1',
    value: 'gradual_ramp1',
    image: '../../colorRampImg/gradual_ramp1.png',
  },
  {
    id: 2,
    label: '色带2',
    value: 'gradual_ramp2',
    image: '../../colorRampImg/gradual_ramp2.png',
  },
  {
    id: 3,
    label: '色带3',
    value: 'gradual_ramp3',
    image: '../../colorRampImg/gradual_ramp3.png',
  },
  {
    id: 4,
    label: '色带4',
    value: 'gradual_ramp4',
    image: '../../colorRampImg/gradual_ramp4.png',
  },
  {
    id: 5,
    label: '色带5',
    value: 'gradual_ramp5',
    image: '../../colorRampImg/gradual_ramp5.png',
  },
  {
    id: 6,
    label: '色带6',
    value: 'gradual_ramp6',
    image: '../../colorRampImg/gradual_ramp6.png',
  },
]);
const drawCircle = (canvas: HTMLCanvasElement, color: string) => {
  // console.log(singleValueRenderParams)
  // let canvas = document.getElementById('graphPreview') as any
  const ctx = canvas.getContext('2d') as any;
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  const radius = 8;
  // const color = singleColor.value
  const circleOpacity = 100;
  // console.log(radius, color)

  // const { outline, outlineColor, outlineOpacity, outlineWidth } = singleValueRenderParams.value.style.point
  const centerX = canvas.width / 2;
  const centerY = canvas.height / 2;

  ctx.globalAlpha = circleOpacity / 100;
  ctx.beginPath();
  ctx.arc(centerX, centerY, radius, 0, 2 * Math.PI);
  ctx.fillStyle = color;
  ctx.fill();
  ctx.closePath();
};
const drawLine = (
  canvas: HTMLCanvasElement,
  colors: string[],
  width: number,
) => {
  // console.log(singleValueRenderParams)
  // let canvas = document.getElementById('graphPreview') as any
  const ctx = canvas.getContext('2d') as any;
  // const color = singleColor.value
  const lineOpacity = 100;
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  const gradient = ctx.createLinearGradient(0, 0, canvas.width, 0);
  gradient.addColorStop(0, colors[0]); // 起始颜色
  gradient.addColorStop(1, colors[1]); // 终止颜色

  // 设置线条样式为渐变
  ctx.strokeStyle = gradient;
  // ctx.strokeStyle = color;
  ctx.lineWidth = width;
  ctx.globalAlpha = lineOpacity / 100;
  // console.log(currentLineType.value)
  // console.log(ctx.lineDash)
  ctx.beginPath();
  // ctx.moveTo(50, 50);
  // ctx.lineTo(350, 50);
  if (ODOptions.isFieldBasedRender) {
    ctx.moveTo(5, 7);
    ctx.lineTo(135, 7);
  } else {
    ctx.moveTo(50, 50);
    ctx.lineTo(350, 50);
  }
  ctx.stroke();
};
const drawLegend = () => {
  if (ODOptions.isFieldBasedRender) {
    ODOptions.paintBasedField['source-color'] = ODOptions.paint['source-color'];
    const startPoints = document.querySelectorAll('.start-point');
    const endPoints = document.querySelectorAll('.end-point');
    const lines = document.querySelectorAll('.line');
    ODOptions.paintBasedField['target-color'] =
      gradualValueRender.getColorRampArray(colorRamp.value, startPoints.length);
    ODOptions.paintBasedField['line-width'] =
      hierarchicalRender.getCircleRadiusArr(
        lineWidthRange.value,
        startPoints.length,
      );
    for (const [i, startPoint] of startPoints.entries()) {
      drawCircle(
        startPoint as HTMLCanvasElement,
        ODOptions.paint['source-color'],
      );
      drawCircle(
        endPoints[i] as HTMLCanvasElement,
        ODOptions.paintBasedField['target-color'][i] as string,
      );
      drawLine(
        lines[i] as HTMLCanvasElement,
        [
          ODOptions.paintBasedField['source-color'],
          ODOptions.paintBasedField['target-color'][i] as string,
        ],
        ODOptions.paintBasedField['line-width'][i] as number,
      );
    }
  } else {
    const canvas = document.querySelector('#graphPreview');
    drawLine(
      canvas as HTMLCanvasElement,
      [ODOptions.paint['source-color'], ODOptions.paint['target-color']],
      ODOptions.paint['line-width'],
    );
  }
};
const handleColorRampSelectChange = (val: any) => {
  // 如果当前已选择字段，改变色带选择将重新绘制图例
  if (ODOptions.field) {
    drawLegend();
  }

  let img = null;
  colorRampList.value.forEach((item: any) => {
    if (item.value === val) {
      img = item.image;
    }
  });
  // console.log(img)
  colorRampSelect.value.$el.children[0].children[0].children[1].setAttribute(
    'style',
    `
        background: url(${img}) no-repeat;
				background-position: 10px center;
				background-size: 80px 20px;
				text-indent: 100px;
				`,
  );
};

// 请求当前图层字段值
const requestFields = async () => {
  fieldList.value = await vectorServiceApi.getFieldsFromGeojson(
    currentLayer.value.source,
  );
};
// 根据选择的字段获取其中的唯一值
const handleFieldSelectChange = async (val: any) => {
  // console.log(currentLayer.value.layerName);
  const uniqueValues = await vectorServiceApi.getUniqueValuesFromGeojson(
    currentLayer.value.source,
    val,
    ODOptions.sort,
  );
  currentLegendList.value = uniqueValues.map((item: any) => ({
    uniqueValue: item,
  })); // 以对象数组形式接收，给定value属性，方便表格显示
  nextTick(() => {
    drawLegend();
  });
};
const handleSortChange = async (val: any) => {
  if (ODOptions.field) {
    const uniqueValues = await vectorServiceApi.getUniqueValuesFromGeojson(
      currentLayer.value.source,
      ODOptions.field,
      val,
    );
    currentLegendList.value = uniqueValues.map((item: any) => ({
      uniqueValue: item,
    }));
  }
};
const handIsFieldBased = () => {
  if (ODOptions.isFieldBasedRender) {
    handleColorRampSelectChange('gradual_ramp1'); // 当前默认的色带
  }
  nextTick(() => {
    drawLegend();
  });
};

const getLocation = () => {
  if (address.value) {
    // 创建axios实例
    const instance = axios.create({
      baseURL: '/baidu_api',
    });
    instance
      .get('/geocoding/v3/', {
        params: {
          address: address.value,
          output: 'json',
          ak: 'DpU9GtFoVPlHKM9KH29FpjzfiI4at7iO',
        },
      })
      .then((result: any) => {
        ODOptions.layout['source-position'][0] =
          result.data.result.location.lng;
        ODOptions.layout['source-position'][1] =
          result.data.result.location.lat;
      })
      .catch((error: any) => {
        // 处理请求错误，显示提示信息
        console.error(error);
        ElMessage({
          message: '地址不符合规范，请检查',
          type: 'warning',
        });
      });
  }
};

const drawEntry = () => {
  drawLegend();
};

onMounted(() => {
  publicStore.setRenderOptions(ODOptions);
  drawLegend();
  requestFields();
  // getLocation()
});
// watch(() => ODOptions.paint['source-color'], (newVal) => {
//   ODOptions.paintBasedField['source-color'] = newVal;
// });
watch(
  ODOptions,
  () => {
    publicStore.setRenderOptions(ODOptions);
  },
  {
    deep: true,
  },
);
</script>

<template>
  <div class="all">
    <ElRow class="itemRow">
      <ElCol :span="4">
        <span class="label-style"> 起点位置： </span>
      </ElCol>
      <ElCol :span="20">
        <ElInput
          v-model="address"
          placeholder="请输入地址（省/市/区/街道/门牌号）"
          @change="getLocation"
        />
      </ElCol>
    </ElRow>
    <ElRow class="itemRow">
      <ElCol :span="4">
        <span class="label-style" style="padding-top: 2px"> 起点坐标： </span>
      </ElCol>
      <ElCol :span="2" style="padding-top: 2px">
        <span> 经度： </span>
      </ElCol>
      <ElCol :span="7">
        <ElInput
          v-model="ODOptions.layout['source-position'][0]"
          placeholder="请输入经度"
          @input="
            ODOptions.layout['source-position'][0] = Number(
              ODOptions.layout['source-position'][0],
            )
          "
        />
      </ElCol>
      <ElCol :span="2" :offset="2" style="padding-top: 2px">
        <span> 纬度： </span>
      </ElCol>
      <ElCol :span="7">
        <ElInput
          v-model="ODOptions.layout['source-position'][1]"
          placeholder="请输入纬度"
          @input="
            ODOptions.layout['source-position'][1] = Number(
              ODOptions.layout['source-position'][1],
            )
          "
        />
      </ElCol>
    </ElRow>
    <ElRow class="itemRow">
      <ElCol :span="8">
        <span class="label-style"> 是否依据字段渲染： </span>
      </ElCol>
      <ElCol :span="16">
        <div class="my-2 flex items-center text-sm">
          <ElRadioGroup
            v-model="ODOptions.isFieldBasedRender"
            @change="handIsFieldBased"
            class="ml-4"
          >
            <ElRadio :label="true">开启</ElRadio>
            <ElRadio :label="false">关闭</ElRadio>
          </ElRadioGroup>
        </div>
      </ElCol>
    </ElRow>
    <ElRow class="itemRow" v-if="!ODOptions.isFieldBasedRender">
      <ElCol :span="4">
        <span class="label-style"> 预览： </span>
      </ElCol>
      <ElCol :span="20">
        <div>
          <canvas id="graphPreview" width="380" height="100"></canvas>
        </div>
      </ElCol>
    </ElRow>
    <template v-if="ODOptions.isFieldBasedRender">
      <ElRow class="itemRow">
        <ElCol :span="4">
          <span class="label-style"> 字段： </span>
        </ElCol>
        <ElCol :span="20">
          <ElSelect
            size="small"
            v-model="ODOptions.field"
            placeholder="请选择终点颜色与线宽渲染依据的字段"
            style="width: 100%"
            @change="handleFieldSelectChange"
          >
            <ElOption
              v-for="item in fieldList"
              :key="item"
              :label="item"
              :value="item"
            />
          </ElSelect>
        </ElCol>
      </ElRow>
    </template>
    <template v-if="ODOptions.isFieldBasedRender">
      <ElRow class="itemRow">
        <ElCol :span="4">
          <span class="label-style"> 渐变方式： </span>
        </ElCol>
        <ElCol :span="20">
          <div class="my-2 flex items-center text-sm">
            <ElRadioGroup
              v-model="ODOptions.sort"
              class="ml-4"
              @change="handleSortChange"
            >
              <ElRadio label="asc">按字段值升序</ElRadio>
              <ElRadio label="desc">按字段值降序</ElRadio>
            </ElRadioGroup>
          </div>
        </ElCol>
      </ElRow>
    </template>
    <template v-if="ODOptions.isFieldBasedRender">
      <ElAlert
        v-if="currentLegendList && currentLegendList.length > 1000"
        title="当前字段唯一值数量过多，只展示前1000位"
        :closable="false"
        type="info"
        show-icon
        center
        style="height: 25px"
      />
      <ElRow class="itemRow preview">
        <ElCol :span="4">
          <span class="label-style"> 预览： </span>
        </ElCol>
        <ElCol :span="20" v-show="currentLegendList">
          <ElTable
            :data="
              currentLegendList
                ? currentLegendList.slice(0, 1000)
                : currentLegendList
            "
            style="width: 100%"
            max-height="170"
          >
            <ElTableColumn label="起点" width="70">
              <template #default="">
                <!-- <div>{{ scope.row.color }}</div> -->
                <!-- <div :style="{ 'background-color': scope.row.color }">{{ scope.$index }}</div> -->
                <div>
                  <canvas
                    width="60"
                    height="20"
                    class="start-point"
                    style="margin-top: 2px"
                  ></canvas>
                </div>
              </template>
            </ElTableColumn>
            <ElTableColumn label="终点" width="70">
              <template #default="">
                <div>
                  <canvas
                    width="60"
                    height="20"
                    class="end-point"
                    style="margin-top: 2px"
                  ></canvas>
                </div>
              </template>
            </ElTableColumn>
            <ElTableColumn label="线条" width="150">
              <template #default="">
                <div>
                  <canvas
                    width="140"
                    height="20"
                    class="line"
                    style="margin-top: 2px"
                  ></canvas>
                </div>
              </template>
            </ElTableColumn>
            <!-- <canvas width="200" height="20" id="mfz"></canvas> -->
            <ElTableColumn prop="uniqueValue" label="唯一值" width="120" />
          </ElTable>
          <!-- <canvas id="graphPreview" width="380" height="100"></canvas> -->
        </ElCol>
      </ElRow>
    </template>
    <ElRow class="itemRow">
      <ElCol :span="24">
        <ElCollapse v-model="activeNames" accordion>
          <ElCollapseItem title="渲染参数" name="renderParams">
            <ElRow class="itemRow">
              <ElCol :span="4">
                <span class="label-style"> 起点颜色： </span>
              </ElCol>
              <ElCol :span="20">
                <ElInput
                  @input="drawEntry"
                  class="colorInput"
                  v-model="ODOptions.paint['source-color']"
                  type="color"
                />
              </ElCol>
            </ElRow>
            <ElRow class="itemRow" v-if="!ODOptions.isFieldBasedRender">
              <ElCol :span="4">
                <span class="label-style"> 终点颜色： </span>
              </ElCol>
              <ElCol :span="20">
                <ElInput
                  @input="drawEntry"
                  class="colorInput"
                  v-model="ODOptions.paint['target-color']"
                  type="color"
                />
              </ElCol>
            </ElRow>
            <ElRow class="itemRow" v-if="ODOptions.isFieldBasedRender">
              <ElCol :span="4">
                <span class="label-style"> 终点颜色： </span>
              </ElCol>
              <ElCol :span="20">
                <ElSelect
                  ref="colorRampSelect"
                  @change="handleColorRampSelectChange"
                  v-model="colorRamp"
                  placeholder="请选择输入色带"
                  style="width: 100%"
                  size="small"
                >
                  <ElOption
                    v-for="item in colorRampList"
                    :key="item.id"
                    :label="item.label"
                    :value="item.value"
                  >
                    <ElRow type="flex" :gutter="20" justify="center">
                      <ElCol :span="18">
                        <img
                          :src="item.image"
                          style="float: left; height: 30px"
                        />
                      </ElCol>
                      <ElCol :span="6">
                        <span>{{ item.label }}</span>
                      </ElCol>
                    </ElRow>
                  </ElOption>
                </ElSelect>
              </ElCol>
            </ElRow>
            <ElRow class="itemRow" v-if="!ODOptions.isFieldBasedRender">
              <ElCol :span="4">
                <span class="label-style"> 线宽： </span>
              </ElCol>
              <ElCol :span="20">
                <ElInput
                  @input="drawEntry"
                  v-model.number="ODOptions.paint['line-width']"
                  placeholder="Please input"
                >
                  <template #append>像素</template>
                </ElInput>
              </ElCol>
            </ElRow>
            <ElRow class="itemRow" v-if="ODOptions.isFieldBasedRender">
              <ElCol :span="4">
                <span class="label-style"> 线宽范围： </span>
              </ElCol>
              <ElCol :span="2">
                <span class="label-style">Min：</span>
              </ElCol>
              <ElCol :span="5">
                <ElInput
                  v-model.number="lineWidthRange[0]"
                  placeholder="Please input"
                  style="margin-top: 2px"
                  @change="drawEntry"
                >
                  <template #append>px</template>
                </ElInput>
              </ElCol>
              <ElCol :span="2" :offset="3">
                <span class="label-style">Max：</span>
              </ElCol>
              <ElCol :span="5">
                <ElInput
                  v-model.number="lineWidthRange[1]"
                  placeholder="Please input"
                  style="margin-top: 2px"
                  @change="drawEntry"
                >
                  <template #append>px</template>
                </ElInput>
              </ElCol>
            </ElRow>
          </ElCollapseItem>
          <ElCollapseItem title="其他样式" name="otherStyle">
            <ElRow class="itemRow">
              <ElCol :span="4">
                <span class="label-style"> 高度： </span>
              </ElCol>
              <ElCol :span="20">
                <ElInput
                  v-model.number="ODOptions.layout.height"
                  placeholder="Please input"
                >
                  <template #append>像素</template>
                </ElInput>
              </ElCol>
            </ElRow>
            <ElRow class="itemRow">
              <ElCol :span="8">
                <span class="label-style"> 是否开启最短路径： </span>
              </ElCol>
              <ElCol :span="16">
                <div class="my-2 flex items-center text-sm">
                  <ElRadioGroup
                    v-model="ODOptions.layout['is-great-circle']"
                    class="ml-4"
                  >
                    <ElRadio :label="true">开启</ElRadio>
                    <ElRadio :label="false">关闭</ElRadio>
                  </ElRadioGroup>
                </div>
              </ElCol>
            </ElRow>
          </ElCollapseItem>
        </ElCollapse>
      </ElCol>
    </ElRow>
  </div>
</template>

<style scoped>
.all {
  width: 100%;
}

.itemRow {
  width: 100%;
  padding: 5px;
}

.preview {
  height: 170px;
}

.el-input {
  width: 100%;
}

.label-style {
  font-size: 15px;
}

.colorInput {
  caret-color: transparent;
}

:deep(.colorInput .el-input__inner:hover) {
  cursor: pointer;
}

:deep(.el-table .el-table__cell) {
  text-align: center;
}

:deep(.el-table:not(.el-table--border) .el-table__cell) {
  border: none;

  /* 去除表格边框 */
}

:deep(.el-table--small .cell) {
  height: 25px;
  padding: 0 4px;
}

:deep(.el-collapse-item__header) {
  font-size: 15px;
  font-weight: 600;
}
</style>
